<template>
    <textarea
            ref="theInput"
            @keydown.enter.ctrl.exact="endPickingTheSentence"
            @keydown.enter.exact="currentPhraseOWordPickComplete"
            @keydown.space.exact="pickNextWord"
            v-model="currentInputingValue"
            style="width: 70%;height:30px;resize: vertical">
    </textarea>
  <!--    <el-icon><CircleCheckFilled /></el-icon>-->
  <!--    <el-icon><BottomLeft /></el-icon>-->
  <!--    <el-icon><DArrowRight /></el-icon>-->
    <br/>
    <el-button @click="pickNextWord" :icon="ArrowRight" class="smallTheElButton"></el-button>
    <el-button @click="backToPrevious" :icon="ArrowLeft" class="smallTheElButton"></el-button>
    <el-button @click="currentPhraseOWordPickComplete" :icon="Check" class="smallTheElButton"></el-button>
    <el-button @click="clearAllPickInputing" :icon="Close" class="smallTheElButton"></el-button>
    <el-button @click="endPickingTheSentence" :icon="Finished" class="smallTheElButton"></el-button>
  <!--    <el-button @click="endPickingTheSentence" :icon="CircleCheckFilled" class="smallTheElButton"></el-button>-->
  <!--    <input type="text"-->
  <!--           ref="theInput"-->
  <!--           @keydown.enter.ctrl.exact="endPickingTheSentence"-->
  <!--           @keydown.enter.exact="currentPhraseOWordPickComplete"-->
  <!--           @keydown.space.exact="pickNextWord"-->
  <!--           v-model="currentInputingValue" style="width: 80%"/>-->
</template>

<script setup>

import {
    ref,
    onMounted,
    computed,
    defineEmits,
    defineProps,
    defineExpose,
    watch,
    getCurrentInstance,
    onBeforeUnmount,
    inject, provide
} from "vue";
import {useInputingStore} from "@/stores/inputingStore.js";
// import isValidObj from "@/utils/ObjectUtils";
// import getWords from "@/utils/RegexUtils"
import {getWords, getRegExpMatchArr} from "@/utils/RegexUtils";
// import PhraseOWordUsage from "@/models/PhraseOWordUsage";
// import isValidObj from "@/utils/ObjectUtils";
import {isValidObj} from "@/utils/ObjectUtils";
import {isInIOS} from "@/utils/EnvInfUtils";
import {lijuContextEventProcessors, lijuContextSW, phraseOWordPickInputEventProvides} from "@/components/constants";
import {
    Check,
    Close,
    CircleCheckFilled,
    BottomLeft,
    DArrowRight,
    Finished,
    CloseBold,
    Right,
    Back,
    DArrowLeft,
    CaretLeft,
    CaretRight,
    ArrowRight,
    ArrowLeft
} from "@element-plus/icons-vue";
import {globalContextSw} from "@/constants/gConstants";
import PhraseOWordUsage from "@/models/PhraseOWordUsage";
// import {onBeforeUnmount} from "@vue/runtime-core";

const theProps = defineProps(["isCurrPickingMarkShowing", "nodeWordsMapping", "thePhraseOWordUsage", "pickMode"]);

const emit = defineEmits(["endPickingTheSentence", "boldAllPickedPhrasesOWords", "clearAllCurrTempMarkingInfo", "clearBoldsOfCurrTempPhraseOWord", "pickKeyingSettled", "showMarkCurrPicking", "boldCurrTempPhraseOWord", "markShowAllThosePhrasesOWords", "inputValueChange"])

const lijuContextSWs = inject(lijuContextSW, undefined);
const globelSw = inject(globalContextSw, undefined);

// let currComingToEnd = false;
let theInput = ref();
let currentInputingValue = ref("");

const {Bus} = getCurrentInstance().appContext.config.globalProperties;

// let $bus = getCurrentInstance().appContext.config.globalProperties.$bus;

function enableTheInput() {
    theInput.value.disabled = null;
    theInput.value.focus();
}

function disableTheInput() {
    theInput.value.disabled = "disabled";
    theInput.value.blur();
    // theInput.value.focus();
}

function setCurrentInputingValue(value) {
    currentInputingValue.value = value;
}

// watch(currentInputingValue,(aa,bb,cc,dd,ee)=>{
watch(currentInputingValue, (newVal, oldVal) => {
//     console.log("watching currentInputingValue with:",aa,bb,cc,dd,ee);

    if (newVal.trim() !== oldVal.trim()) {
        showMarkCurrPicking();
    }

    // emit("inputValueChange","inputing value changed with aa:"+aa+" ,bb : "+bb+" ,cc : "+cc+" ,dd : "+dd+" ,ee : "+ee);
});

const theInputingStore = useInputingStore();
theInputingStore.currFilledMoreThanOne = false;

/**
 *
 * @type {UnwrapRef<UnwrapNestedRefs<{currTempPhraseOWord: PhraseOWordUsage.PhraseOWord, pickInputingValue: string, iskeyingSettled: boolean, count: number, name: string, currFilledMoreThanOne: boolean}>["currTempPhraseOWord"]>}
 */
const currTempPhraseOWord = theInputingStore.currTempPhraseOWord;
initTheStoreData();

let currentInputingWords = computed(() => {
    return getWords(currentInputingValue.value);
});

let extractAWordRegex = computed(() => {
    return new RegExp("\\b" + currentInputingValue.value.trim() + "[a-zA-Z]*\\b", "ig");
});

// function markShowAllThosePhrasesOWords() {
//     // console.log(theProps);
//     // console.log("emitting....")
//     emit('markShowAllThosePhrasesOWords', new PhraseOWordUsage.PhraseOWord(new PhraseOWordUsage.WordMark(0, "ssss"), new PhraseOWordUsage.WordMark(3, "aaaa"), true))
// }

function initTheStoreData() {
    theInputingStore.pickInputingValue = "";
    theInputingStore.iskeyingSettled = false;
    theInputingStore.currFilledMoreThanOne = false;
    theInputingStore.currTempPhraseOWord.liju = theProps.thePhraseOWordUsage.liju;
    clearMarkDataIndex();
}

let phraseOWordPickInputEvtProvides = inject(phraseOWordPickInputEventProvides, undefined);

function endPickingTheSentence(e) {
    // console.log("endPickingTheSentence with ", e);
    disableTheInput();
    currentPhraseOWordPickComplete(e);
    initTheStoreData();
    theInput.value.removeEventListener("keydown", preventInvalidOper);
    emit("endPickingTheSentence");
    phraseOWordPickInputEvtProvides.endPhraseOWordIputPicking?.();
    setTimeout(() => {
        // Bus.emit('endPickingTheSentence', theProps.thePhraseOWordUsage.id);
        // theProps.theLijuEntry.phrasingIt = false;
        lijuContextSWs.phrasingIt.value = false;
        if(globelSw.anyIndividualIsEditing.value>0){
            globelSw.anyIndividualIsEditing.value = globelSw.anyIndividualIsEditing.value - 1;
        }
    }, 100);

}

function currentPhraseOWordPickComplete(e) {
    if (currTempPhraseOWord.isValidPhraseOWord) {
        let toAddPhraseOWord;
        if(theProps.pickMode === 'word'){
          toAddPhraseOWord = new PhraseOWordUsage.Word(currTempPhraseOWord.startWordMark.clone(),currTempPhraseOWord.endWordMark.clone(),currTempPhraseOWord.liju,currTempPhraseOWord.isValidPhraseOWord)
        }else{
          toAddPhraseOWord = new PhraseOWordUsage.Phrase(currTempPhraseOWord.startWordMark.clone(),currTempPhraseOWord.endWordMark.clone(),currTempPhraseOWord.liju,currTempPhraseOWord.isValidPhraseOWord)
        }
        theProps.thePhraseOWordUsage.addPhraseOWord(toAddPhraseOWord);
        clearAllCurrTempMarkingInfo();
        currentInputingValue.value = "";
        theInputingStore.currFilledMoreThanOne = false;
        enableTheInput();
        // console.log("currentPhraseOWordPickComplete with ", e);
    }
    e.preventDefault();
}

theInputingStore.currFilledMoreThanOne = false;

function clearAllPickInputing() {
    clearAllCurrTempMarkingInfo();
    theInputingStore.currFilledMoreThanOne = false;
    currentInputingValue.value = "";
    enableTheInput();
}

function pickNextWord(e) {
    // console.log("is the obj valid");
    // console.log("pickNextWord with ", e);

    if (isValidObj(currentInputingValue.value) && currentInputingValue.value.trim() === "") {
        e.preventDefault();
        return;
    }

    //todo 从已经选择了多于一个词到，全选后再输入一个没选择的词时判断
    if (theInputingStore.currFilledMoreThanOne && currentInputingWords.value.length === 1) {
        clearAllCurrTempMarkingInfo();
        e.preventDefault();
        // return;
    }

    //todo 全选后按空格为删除
    if (theInputingStore.currFilledMoreThanOne && theInput.value.selectionStart === 0 && theInput.value.selectionEnd === currentInputingValue.value.length) {
        clearAllPickInputing();
        e.preventDefault();
        return;
    }

    if (currentInputingWords.value.length === 1) {
        // currComingToEnd = false;

        if (!currTempPhraseOWord.isStartWordMarkValid) {

            let regExpMatchArr = getRegExpMatchArr(theProps.thePhraseOWordUsage.eng, extractAWordRegex.value);
            regExpMatchArr = regExpMatchArr.filter((theRegExpMatch) => {
                return !theProps.thePhraseOWordUsage.anyInPickedPhase(theRegExpMatch.index);
            })

            // console.log("m2");

            if (regExpMatchArr.length === 0) {
                // console.log("非法输入");
                e.preventDefault();
            } else if (regExpMatchArr.length === 1) {
                // console.log("唯一合法，放行");
                currentInputingValue.value = regExpMatchArr[0][0];
                currTempPhraseOWord.startWordMark.startIdx = regExpMatchArr[0].index;
                currTempPhraseOWord.startWordMark.word = regExpMatchArr[0][0];
                // markEndIdx = markStartIdx + regExpMatchArr[0][0].length;
                currTempPhraseOWord.endWordMark.startIdx = regExpMatchArr[0].index;
                currTempPhraseOWord.endWordMark.word = regExpMatchArr[0][0];
                currTempPhraseOWord.isValidPhraseOWord = true;
                theInputingStore.currFilledMoreThanOne = false;
                emit("boldCurrTempPhraseOWord", currTempPhraseOWord);
                e.preventDefault();
            }
            // else {
            //     // console.log("m5");
            // }

        } else if (theProps.pickMode === 'word') {
            return;
        } else {
            // console.log("填入第二个单词逻辑");
            e.preventDefault();
            fillInNextWordDefault()
        }

    } else {
        // console.log("输入框内两个及以上单词逻辑");
        fillInNextWordDefault()
        e.preventDefault();
    }
}

function fillInNextWordDefault() {
    // logTheResult("fillInNextWordDefault start");
    // var restStr = eng.substring(markEndIdx, eng.length - 1);
    var restStr = theProps.thePhraseOWordUsage.eng.substring(currTempPhraseOWord.endWordMark.startIdx + currTempPhraseOWord.endWordMark.word?.length);
    // logTheResult("fillInNextWordDefault restStr :"+restStr);
    let nextWordMatch = restStr.match(/[a-zA-Z]+/i);
    // logTheResult("fillInNextWordDefault nextWordMatch :"+nextWordMatch);
    if (!nextWordMatch) {
        // currComingToEnd = true;
        // console.log(currComingToEnd)
        // theInput.value.disabled = "disabled";
        theInput.value.blur();
    } else {
        let netxtWordStartIdxInSentence = currTempPhraseOWord.endWordMark.startIdx + currTempPhraseOWord.endWordMark.word.length + nextWordMatch.index;
        // theProps.thePhraseOWordUsage.eng.substring(currTempPhraseOWord.startWordMark.startIdx, currTempPhraseOWord.endWordMark.startIdx + currTempPhraseOWord.endWordMark.word.length + nextWordMatch.index + nextWordMatch[0].length)
        let nextWordAllText = theProps.thePhraseOWordUsage.eng.substring(
            currTempPhraseOWord.startWordMark.startIdx,
            currTempPhraseOWord.endWordMark.startIdx + currTempPhraseOWord.endWordMark.word.length
            + nextWordMatch.index + nextWordMatch[0].length);
        if (!theProps.thePhraseOWordUsage.anyInPickedPhase(netxtWordStartIdxInSentence) && theProps.thePhraseOWordUsage.eng !== nextWordAllText) {
            // logTheResult("fillInNextWordDefault resultstr :"+eng.substring(markStartIdx,nextWordEndIdx));
            currentInputingValue.value = nextWordAllText;
            currTempPhraseOWord.endWordMark.startIdx = netxtWordStartIdxInSentence;
            currTempPhraseOWord.endWordMark.word = nextWordMatch[0];
            emit("boldCurrTempPhraseOWord", currTempPhraseOWord);
            theInputingStore.currFilledMoreThanOne = true;
            fillInTheInputWithCurrTempPhraseOWord();
            if (isInIOS()) {
                disableTheInput();
            }
            // boldTheSelectedWords(markStart.startIdx, markEnd.startIdx);
        }
    }
}

function fillInTheInputWithCurrTempPhraseOWord() {
    currentInputingValue.value = theProps.thePhraseOWordUsage.eng.substring(currTempPhraseOWord.phraseOWordStartIndex, currTempPhraseOWord.phraseOWordEndIndex);
}

function clearAllCurrTempMarkingInfo() {
    emit("clearAllCurrTempMarkingInfo");
    clearMarkDataIndex();
    // currentInputingValue.value="";
    emit("boldAllPickedPhrasesOWords");
}

function clearMarkDataIndex() {
    theInputingStore.currTempPhraseOWord.startWordMark.initIndex();
    theInputingStore.currTempPhraseOWord.endWordMark.initIndex();
    theInputingStore.currTempPhraseOWord.isValidPhraseOWord = false;
}

let isKeyingSettled = true;
let checkSettledTimer;
let cnt = 0
let startTime = Date.now()

function showMarkCurrPicking() {
    // let notWatchingKeys = isAllowedKey;
    if (currentInputingWords.value.length === 1) {
        watchSettled();

        //timeout 毫秒数
        // console.log("iskeyingsettled",isKeyingSettled);
        // setTimeout(()=>{}, 500 );
        // console.log("currentInputingValue value",currentInputingValue.value);
        // console.log("currentInputingValue e.target.value",e.target.value);
        theInputingStore.pickInputingValue = currentInputingValue.value;
        // theInputingStore.testOnAction();

        if (!currTempPhraseOWord.isValidPhraseOWord) {
            emit('showMarkCurrPicking');
        } else if (theInputingStore.currFilledMoreThanOne) {
            clearAllCurrTempMarkingInfo();
            emit('showMarkCurrPicking');
        }
    }

    // let isNotWatchKeys = isAllowedKey;
    // function isNotWatchKeys() {
    //     // let notWatchingKeys = ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Enter", "Control", "Shift", "Alt", " ", "Tab", "Meta", "Home", "End"];
    //     // let index = notWatchingKeys.findIndex((key) => {
    //     //     return e.key === key;
    //     // });
    //     //
    //     // return index>-1;
    // }

    function watchSettled() {

        isKeyingSettled = false;
        if (!isValidObj(checkSettledTimer)) {
            // console.log("keying setting interval");
            checkSettledTimer = setInterval(() => {
                // console.log("checkSettledTimer keying interval going...",isKeyingSettled);
                if (isKeyingSettled && currentInputingValue.value !== "") {
                    // console.log(`keying settleed....from last ${Date.now() - startTime}ms //` + (cnt++));
                    startTime = Date.now();
                    clearInterval(checkSettledTimer);
                    if (theProps.isCurrPickingMarkShowing) {

                        //todo mark
                        emit('pickKeyingSettled');
                    }
                    checkSettledTimer = null;
                }
            }, 211);
        }

        setTimeout(() => {
            startTime = Date.now();
            isKeyingSettled = true;
        }, 233);
    }

    // }
}

function backToPrevious(e) {
    if (currentInputingWords.value.length > 1) {
        if (theInput.value.selectionStart !== 0 || theInput.value.selectionEnd !== currentInputingValue.value.length) {
            var preWordNodeOfLast = theProps.nodeWordsMapping.wordSpanNodes[theProps.nodeWordsMapping["word" + currTempPhraseOWord.endWordMark.startIdx] - 1];
            currTempPhraseOWord.endWordMark.startIdx = preWordNodeOfLast.idx;
            currTempPhraseOWord.endWordMark.word = preWordNodeOfLast.word;
            emit("boldCurrTempPhraseOWord")
            fillInTheInputWithCurrTempPhraseOWord();
            e.preventDefault();
        } else {
            clearAllCurrTempMarkingInfo();
        }
    } else {
        clearAllCurrTempMarkingInfo();
        theInputingStore.currFilledMoreThanOne = false;
        if (isInIOS()) {
            // showMarkCurrPicking();
            enableTheInput();
        }
    }
}

function preventInvalidOper(e) {
    if ("Enter" === e.code && e.ctrlKey) {
        return;
    }
    if ("Space" === e.code) {
        e.preventDefault();
    }
    // console.log("preventInvalidOper with:",e.code,e.ctrlKey)
    // console.log("preventInvalidOper start with:",e.key);
    if (e.code === "Backspace") {
        backToPrevious(e);
    }

    // console.log("e.code:",e.code,e.key);
    if (currentInputingWords.value.length > 1 && e.code !== "Space") {
        // console.log("preventInvalidOper with ",e);

        if (e.key === "Delete") {
            // console.log("the input selectionStart:", theInput.value.selectionStart);
            if (theInput.value.selectionStart !== 0 || theInput.value.selectionStart !== currentInputingValue.value.length) {
                // logTheResult("mark1")
                //todo #mark1
                e.preventDefault();
                return;
            }
        }

        if (theInput.value.selectionStart === theInput.value.selectionEnd && !isAllowedKey(e.key)) {
            // logTheResult("mark2")
            e.preventDefault();
            return;
        }
    }

    if ("1234567890".indexOf(e.key) > -1) {
        e.preventDefault();
        // return;
    }else{
        e.stopPropagation();
    }

    // console.log("preventInvalidOper end with:",e.key);
}

const allowKey = ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Enter", "Control", "Shift", "Alt", " ", "Tab", "Meta", "Home", "End"];

function isAllowedKey(key) {
    for (const keyAllow of allowKey) {
        if (keyAllow === key) {
            return true;
        }
    }
}

onMounted(() => {
    // theInput.value.addEventListener("keydown", preventInvalidOper,{passive:false});
    theInput.value.addEventListener("keydown", preventInvalidOper);
    theInput.value.focus();
    // theInput.value.addEventListener("keyup", showMarkCurrPicking);
})

onBeforeUnmount(() => {
    theInput.value.removeEventListener("keydown", preventInvalidOper);
    // console.log("")
})

defineExpose({
    enableTheInput,
    setCurrentInputingValue,
    isAllowedKey,
    disableTheInput
});

</script>

<style scoped>

</style>